package fr.inpl_nancy.mines.andromines.envemu;

import java.net.*;
import java.io.*;
import java.util.*;

/**
 * Class used to make the link between the environment emulator
 * and the fake bluetooth/geoloc/other interface using sockets.
 * (Singleton design pattern)
 * 
 * @author Olivier Genest
 * @version 0.1
 * 
 */
public class EnvironmentEmulation {

	//Environment emulation object (Singleton design pattern)
	private static EnvironmentEmulation env = null;

	//Map that contains the link between data types & upper layer
	private Map<String, EnvironmentEmulationInterface> map;
	
	//Address of the environment simulator server
	private final static String HOST = "localhost";
	private final static int PORT = 1338;
	
	
	/**
	 * Private constructor (Singleton design pattern)
	 */
	private EnvironmentEmulation() {
		this.map = new HashMap<String, EnvironmentEmulationInterface>();
	}

	/**
	 * Only way to access to the EnvironmentEmulation object
	 * 
	 * @return Unique EnvironmentEmulation object
	 */
	public static EnvironmentEmulation getEnvironmentEmulation() {
		if(env == null) env = new EnvironmentEmulation();
		return env;
	}
	
	/** Function that run the socket server
	 * 
	 * @param ServerPort Port to listen
	 */
	public void runSocketServer(int ServerPort) {
		ServerSocket laSocket = null;
		
		//ServerSocket creation
		try {
			laSocket = new ServerSocket(ServerPort);
		} catch(IOException e) {}
		
		while(true) {
		//Connection treatment
			try {
				new EnvironmentEmulationConnectionHandler(laSocket.accept()).start();
			} catch(Exception e) {}
		}
		
	}
	
	/**
	 * Function that can be called by the upper layer to 
	 * send data to the environment simulator
	 * 
	 * @param host Environment simulator server hostname
	 * @param port Environment simulator server port
	 * @param message Data to send
	 */
	public void sendSocket(String message) {
		String answer = "";
		
		//Creating the socket
		Socket laSocket = null;
		
		try {
			
			//Trying to connect
			try {
				laSocket = new Socket(HOST,PORT);
			} catch(UnknownHostException e) {
				System.out.println("Unknown host !");
			}
			
			//Connecting the streams
			PrintStream sortie = new PrintStream(laSocket.getOutputStream());
			BufferedReader entree = new BufferedReader(new InputStreamReader(laSocket.getInputStream()));
			
			//Sending the request
			sortie.println(message);

			
		} catch(IOException e) {}
		
	}
	
	/**
	 * Function that allow an upper layer to register itself 
	 * as a specified kind of data treatment class
	 * 
	 * @param name Data type concerned
	 * @param upperLayer Upper layer
	 */
	public void register(String name, EnvironmentEmulationInterface upperLayer) {
		map.put(name, upperLayer);
	}
	
	/**
	 * Function that allow the EnvironmentEmulationConnectionHandler 
	 * to get the upper layer that has to treat a type of data
	 * 
	 * @param name Type of data
	 * @return Upper layer
	 */
	public EnvironmentEmulationInterface getUpperLayer(String name) {
		return map.get(name);
	}
	
	
}
